﻿using System;
using System.Collections.Generic;
#if DEBUG
using System.Diagnostics;
#endif // #if DEBUG
using System.IO;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

using FRL.DebtChased.Repository;
using FRL.DebtChased.Repository.ViewModels;
using FRL.DebtChased.Website;

namespace FRL.DebtChased.Website.ClientZone
{

	/// <summary>
	/// Declaration of Documents class
	/// </summary>
	public partial class Documents : System.Web.UI.Page
	{

		/////////////////////////////////////////////////////////////
		// Nested classes

		/////////////////////////////////////////////////////////////
		// Constants

		private const string ContextTag = "ContextTag";

		/////////////////////////////////////////////////////////////
		// Attributes

		private bool m_bRebind = false;

		private string m_strSearchAccRef = null;

		private DocumentModel.Element ContextObject
		{
			get { return ViewState[ContextTag] as DocumentModel.Element; }
			set { ViewState[ContextTag] = value; }
		}

		/////////////////////////////////////////////////////////////
		// Events Handler

		protected override void OnPreRender(EventArgs e)
		{

			// Call base-class function
			base.OnPreRender(e);

			// If rebinding or searching...
			if ( (m_bRebind) || (m_strSearchAccRef != null) )
			{

				// Bind the session
				MySession mySession = MySession.BindMySession();

				// Declare an entity object
				using (DebtChasedEntities ent = new DebtChasedEntities())
				{

					// If rebinding...
					if (m_bRebind)
					{

						// Declare the model object
						DocumentModel m = null;

						// Load the error-log model
						m = new DocumentModel(ent, mySession.ClientID, "~/Uploads/Documents");

						// Load the grid
						gridResult.DataSource = m.Elements;
						gridResult.DataBind();

					}

					// If searching...
					if (m_strSearchAccRef != null)
					{

						// Load map and bind to check list
						AccountInvoiceModel m = new AccountInvoiceModel( ent, m_strSearchAccRef );
						gridAvailable.DataSource = m.Elements;
						gridAvailable.DataBind();

						// Reset search string
						m_strSearchAccRef = null;

					}

				}

			}

			// Hide/show controls
			pnlAdd.Visible = (this.ContextObject != null) && (this.ContextObject.DocumentId == 0);
			pnlEdit.Visible = (this.ContextObject != null) && (this.ContextObject.DocumentId != 0);

		}

		protected void Page_Load(object sender, EventArgs e)
		{

			// If this is a postback...
			if (this.IsPostBack)
			{

			}
			else
			{

				// Bind the session
				MySession mySession = MySession.BindMySession();

				// Debug client id
#if DEBUG
				if (mySession.UserID == 0)
					mySession.SetDummyClient();
#endif // #if DEBUG

				// Rebind the grid
				m_bRebind = true;

				// Set panel colours
				MyApplication myApp = MyApplication.BindMyApplication();
				pnlResults.BackColor = myApp.PrimaryWebColor;
				pnlAdd.BackColor = myApp.PrimaryWebColor;
				pnlEdit.BackColor = myApp.PrimaryWebColor;

				// Start with an add option
				butAdd_Click(null, null);

			}

		}

		protected void gridResult_RowCommand(object sender, GridViewCommandEventArgs e)
		{

			// Compare commands
			if (e.CommandName == "Select")
			{

				// Check the grid view object
				GridView gridView = sender as GridView;
#if DEBUG
				System.Diagnostics.Trace.Assert(gridView == gridResult);
#endif // #if DEBUG

				// Get row index			
				int iRow = int.Parse(e.CommandArgument.ToString());

				// Get the document id
				int iDocumentId = int.Parse(gridResult.DataKeys[iRow].Value.ToString());

				// Load the document details
				using (DebtChasedEntities ent = new DebtChasedEntities())
				{
					ContextObject = new DocumentModel.Element(ent, iDocumentId);
				}
				txtDocumentName.Text = ContextObject.DocumentName;
				gridInvoice.DataSource = ContextObject.AccountInvoices.Elements;
				gridInvoice.DataBind();

			}

		}

		protected void gridResult_RowDataBound(object sender, GridViewRowEventArgs e)
		{

			// If this is a data row...
			if (e.Row.RowType == DataControlRowType.DataRow)
			{

				// Get the element
				DocumentModel.Element el = e.Row.DataItem as DocumentModel.Element;

				// Get the delete button
				Button butDeleteDocument = e.Row.FindControl("butDeleteDocument") as Button;
				butDeleteDocument.Enabled = (!el.InUse);

			}

		}

		protected void butDeleteDocument_Click(object sender, EventArgs e)
		{

			// Declaration of local variables
			string strError = null;

			// Get the current user
			int iUserId = MySession.BindMySession().UserID;
#if DEBUG
			if (iUserId != 0)
				iUserId = 1;
#endif // #if DEBUG

			// Get the document folder path
			string strDocumentFolderPath = Server.MapPath("~/Uploads/Documents");

			// Get the selected document id
			GridViewRow row = (sender as Control).GetParentObject(typeof(GridViewRow)) as GridViewRow;
			int iDocumentId = int.Parse(gridResult.DataKeys[row.RowIndex].Value.ToString());

			// Delete the document
			using (DebtChasedEntities ent = new DebtChasedEntities())
			{
				strError = Document.Delete(ent, iDocumentId, strDocumentFolderPath, iUserId);
			}

			// If that worked...
			if (strError == null)
			{
				butCancelEdit_Click(null, null);
				m_bRebind = true;
			}
			else
				(this.Master as ClientMaster).ErrorMessage = strError;

		}

		protected void butAdd_Click(object sender, EventArgs e)
		{

			// Update the context
			ContextObject = new DocumentModel.Element();

		}

		protected void butOKAdd_Click(object sender, EventArgs e)
		{

			// Declaration of local variables
			string strError = null;
			string strFilepath = null;

			// Validate content
			this.Validate();
			if (!this.IsValid)
			{
				(this.Master as ClientMaster).ErrorMessage = this.Validators.ToErrorMessage();
				return;
			}

			// Get user id
			MySession mySession = MySession.BindMySession();
			int iUserId = mySession.UserID;
			int iClientId = mySession.ClientID;

			// Get the context object
			DocumentModel.Element contextElement = ContextObject;
#if DEBUG
			Debug.Assert(contextElement != null);
			Debug.Assert(contextElement.DocumentId == 0);
#endif // #if DEBUG

			// Retain the file extension and file title
			string strExtension = null;

			// Check if uploader was submitted
			if ((fileUpload.PostedFile == null) || (fileUpload.PostedFile.ContentLength == 0))
				strError = "Please specify a Word or PDF file.";
			else if (fileUpload.PostedFile.ContentLength > (1024 * 1024 * 1))
				strError = "Too large.  Imported files can be up to 1Mb.";
			else
			{
				strExtension = Path.GetExtension(fileUpload.PostedFile.FileName);
				if (
					(string.Compare(strExtension, ".docx", true) != 0)
					&&
					(string.Compare(strExtension, ".pdf", true) != 0)
				)
					strError = "Only Microsoft Word files in docx format and PDF files can be imported.";
			}

			// If that worked...
			if (strError == null)
			{

				try
				{

					// Get the documents folder path
					string strDocumentsFolderPath = Server.MapPath("~/Uploads/Documents");

					// Compose a file name
					string strFileName = Document.ComposeNewFilename(strExtension);

					// Compose filepath
					strFilepath = Document.SafeComposeFilepath(strDocumentsFolderPath, strFileName);

					// Upload file
					fileUpload.PostedFile.SaveAs(strFilepath);

					// Compose name
					string strDocumentName = Path.GetFileName(fileUpload.PostedFile.FileName);

					// If this file needs converting...
					if (
						(string.Compare(strExtension, ".docx", true) == 0)
						&&
						(chkConvertToPDF.Checked)
					)
					{

						// Compose new document name and file name
						string strNewFilepath = strFilepath.Substring(0, strFilepath.Length - 5) + ".pdf";

						// Convert file to pdf
						strError = WordSession.ConvertToPdf(strFilepath, strNewFilepath);
						if (strError == null)
						{

							// Delete the old file
							File.Delete(strFilepath);

							// Update names
							strFilepath = strNewFilepath;
							strFileName = Path.GetFileName(strFilepath);
							strDocumentName = strDocumentName.Substring(0, strDocumentName.Length - 5) + ".pdf";

						}

					}

					// Save the document
					using (DebtChasedEntities ent = new DebtChasedEntities())
					{

						// Add the new document
						int iNewDocumentId = 0;
						strError = Document.Add(
							ent,
							iClientId,
							strFileName,
							strDocumentName,
							fileUpload.PostedFile.ContentLength,
							out iNewDocumentId,
							iUserId
						);
						if (strError == null)
						{

							// Load the context again
							ContextObject = new DocumentModel.Element(ent, iNewDocumentId);
							txtDocumentName.Text = ContextObject.DocumentName;
							gridInvoice.DataSource = ContextObject.AccountInvoices.Elements;
							gridInvoice.DataBind();

						}

					}

				}
				catch (Exception x)
				{

					// Process exception
					strError = ErrorProcessing.HandleException(x, "upload document", iUserId);

				}

			}

			// If that worked...
			if (strError == null)
			{

				// Reset context and re-bind
				m_bRebind = true;

			}
			else
			{

				// Delete the uploaded files
				if (File.Exists(strFilepath))
					File.Delete(strFilepath);

				// Show the error
				(this.Master as ClientMaster).ErrorMessage = strError;

			}

		}

		protected void butCancelAdd_Click(object sender, EventArgs e)
		{

			// Update the context
			this.ContextObject = null;

		}

		protected void butOKEdit_Click(object sender, EventArgs e)
		{

			// Declaration of local variables
			string strError = null;

			// Get the current user
			int iUserId = MySession.BindMySession().UserID;
#if DEBUG
			if (iUserId != 0)
				iUserId = 1;
#endif // #if DEBUG

			// Get the context
			DocumentModel.Element el = ContextObject;
			el.DocumentName = txtDocumentName.Text;

			// Declare an entities object
			using (DebtChasedEntities ent = new DebtChasedEntities())
			{
				strError = DocumentModel.Set(ent,el,iUserId);
			}

			// Show error or re-bind
			if (strError == null)
			{
				m_bRebind = true;
				ContextObject = null;
				txtSearchAccRef.Text = string.Empty;
				gridAvailable.DataSource = null;
				gridAvailable.DataBind();
			}
			else
				(this.Master as ClientMaster).ErrorMessage = strError;

		}

		protected void butCancelEdit_Click(object sender, EventArgs e)
		{

			// Reset the context
			this.ContextObject = null;
			txtSearchAccRef.Text = string.Empty;
			gridAvailable.DataSource = null;
			gridAvailable.DataBind();

		}

		protected void butSearchAccRef_Click(object sender, EventArgs e)
		{

			// Validate content
			this.Validate();
			if (!this.IsValid)
			{
				(this.Master as ClientMaster).ErrorMessage = this.Validators.ToErrorMessage();
				return;
			}

			// Search the accounts
			m_strSearchAccRef = txtSearchAccRef.Text;

		}

		protected void gridAvailable_RowCommand(object sender, GridViewCommandEventArgs e)
		{

			// Check the grid view object
			GridView gridView = sender as GridView;
#if DEBUG
			System.Diagnostics.Trace.Assert(gridView == gridAvailable);
#endif // #if DEBUG

			// Get row index
			int iRow = int.Parse(e.CommandArgument.ToString());

			// Get the account-invoice id
			int iAccountInvoiceId = int.Parse(gridAvailable.DataKeys[iRow].Value.ToString());

			// Compare commands
			if (e.CommandName == "Select")
			{

				// Update the context object
				DocumentModel.Element el = ContextObject;
				if (el.AccountInvoices.FindByAccountInvoiceId(iAccountInvoiceId) == null)
				{

					// Add this account-invoice
					using (DebtChasedEntities ent = new DebtChasedEntities())
					{
						AccountInvoiceModel.Element inv = new AccountInvoiceModel.Element( ent, iAccountInvoiceId );
						el.AccountInvoices.Elements.Add(inv);						
					}
					gridInvoice.DataSource = el.AccountInvoices.Elements;
					gridInvoice.DataBind();

				}

			}

		}

		protected void gridInvoice_RowCommand(object sender, GridViewCommandEventArgs e)
		{

			// Check the grid view object
			GridView gridView = sender as GridView;
#if DEBUG
			System.Diagnostics.Trace.Assert(gridView == gridInvoice);
#endif // #if DEBUG

			// Get row index
			int iRow = int.Parse(e.CommandArgument.ToString());

			// Get the account-invoice id
			int iAccountInvoiceId = int.Parse(gridInvoice.DataKeys[iRow].Value.ToString());

			// Compare commands
			if (e.CommandName == "Select")
			{

				// Update the context object
				DocumentModel.Element el = ContextObject;
				AccountInvoiceModel.Element aim = el.AccountInvoices.FindByAccountInvoiceId(iAccountInvoiceId);
				if (aim != null)
				{

					// Remove from context
					el.AccountInvoices.Elements.Remove(aim);

					// Rebind
					gridInvoice.DataSource = el.AccountInvoices.Elements;
					gridInvoice.DataBind();

				}

			}

		}

	}

}